﻿using System;
using System.Collections.Generic;
using System.Windows.Media;

using Bling.Core;
using Bling.DSL;
using Bling.WPF;
using Bling.WPF.Custom;
using Bling.Graphics;
using Bling.DX;
using Bling.Matrices;
using Bling.Angles;

namespace Bling.Example {
  // Basic example of how to use a camera and refer to dependency properties in your shader.
  // Instancing is also introduced.
  public class BasicFaces : HasDX10Canvas {
    public BasicFaces() : base(false) {

      Host.Size = new Double2Bl(500, 500); // host size must be constant!
      Host.LeftTop = 0d;
      // sliders to control camera Z distance as well as X and Y rotation.
      var CameraZ = new LabelSliderBl(this) { LabelName = "Z", Minimum = -40d, Maximum = +10d, Value = -4d, LeftTop = Host.LeftBottom };
      var RotateX = new LabelSliderBl(this) { LabelName = "RotateX", Minimum = 0d, Maximum = 2d, Value = .9d, LeftTop = CameraZ.LeftBottom };
      var RotateY = new LabelSliderBl(this) { LabelName = "RotateY", Minimum = 0d, Maximum = 2d, Value = .9d, LeftTop = RotateX.LeftBottom };

      // A cube vertex topology, 4 vertices per face.
      FaceMesh Face = new FaceMesh();

      //  create a perspective camera.
      Double3Bl WorldCenter = new Double3Bl(0, 0, 0);
      Double3Bl CameraPosition = WorldCenter + new Double3Bl(0, 0, CameraZ.Value);
      PerspectiveCameraCl Camera = new PerspectiveCameraCl() {
        Position = CameraPosition,
        // These are the defaults for the rest
        // Direction = { Look = WorldCenter },
        // FieldOfView = .1d.PI().AsDegrees,
        // PlaneDistance = { Far = 100, Near = .1 },
      };
      Device.Render(Face, 16 /* render 16 cubes */, (IntBl m, FaceMesh.Mesh3DEntry Entry, IVertex vertex) => {
        // n is the vertex index, there are four vertices per face, so divide by 4 to find the face id.
        var face = Entry.Index.PerVertex() / 4;
        // quaternions for both x and y rotation, determined by sliders.
        var qx = new QuaternionBl(new Double3Bl(1, 0, 0), RotateX.Value.PI());
        var qy = new QuaternionBl(new Double3Bl(0, 1, 0), RotateY.Value.PI());
        // compose rotations via quaternion product.
        var q = qx * qy;
        // m is the instance index, there are 16 instances, arrange in a square configuration using %/ by 4.
        var mxy = new Double2Bl(m % 4, m / 4);
        // the current coord is [0,1,2,3] based, we need to convert to [-1,+1] based.
        mxy = (mxy / 4d) - (.5 + .25) / 2d;

        // find the xyz coordinate of the current vertex index
        Double3Bl xyz = Entry.Position;
        xyz = (Camera * Matrix4Bl.MakeTranslate(mxy.AddZ(0)) * Matrix4Bl.MakeScale(.1) * q.Matrix).Transform(xyz);
        vertex.Position = xyz;

        var FaceColors = new ColorBl[] {
          Colors.Red,
          Colors.LightGreen,
          Colors.Blue,
          Colors.Yellow,
          Colors.Purple,
          Colors.Salmon,
        };
        ColorBl clr = FaceColors.Table(face % FaceColors.Length);
        vertex.Color = clr;
      });
      // this will actually cause rendering to occur in a WPF host. 
    }
  }
}
